package com.zhangmeng.service.impl;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.zhangmeng.service.DataPack;
import com.zhangmeng.service.Message;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;


import java.io.*;
import java.nio.ByteBuffer;

import com.zhangmeng.utils.ByteBufferUtil;

/**
 * @author zm
 * @date 2025/2/22 17:36
 * @version: 1.0
 */
public class DataPackImpl implements DataPack {

    private final Log log = LogFactory.get();

    @Override
    public int GetHeadLen() {
        return 8;
    }

    @Override
    public byte[] Pack(Message msg) {

        DataMsg dataMsg = new DataMsg();
        dataMsg.setSequenceId(0);
        dataMsg.setData(msg.GetData());
        dataMsg.setDataLen(msg.GetDataLen());
        dataMsg.setMsgId(msg.GetMsgId());

        try {
            ByteBuf out = Unpooled.buffer();

            // 1. 4 字节的魔数
            out.writeBytes(new byte[]{1, 2, 3, 4});
            // 2. 1 字节的版本,
            out.writeByte(1);
            // 3. 1 字节的序列化方式 jdk 0 , json 1
            out.writeByte(0);
            // 4. 1 字节的指令类型
            out.writeByte(0);
            // 5. 4 个字节
            out.writeInt(dataMsg.getSequenceId());
            // 无意义，对齐填充
            out.writeByte(0xff);
            // 6. 获取内容的字节数组
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(dataMsg);
            byte[] bytes = bos.toByteArray();
            // 7. 长度
            out.writeInt(bytes.length);
            // 8. 写入内容
            out.writeBytes(bytes);
            byte[] data = out.array();
            ByteBufferUtil.debugBuf(data);
            out.release();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public Message Unpack(ByteBuf in) {

        if (in != null) {

            try {
                int magicNum = in.readInt();
                byte version = in.readByte();
                byte serializerType = in.readByte();
                byte messageType = in.readByte();
                int sequenceId = in.readInt();
                in.readByte();
                int length = in.readInt();
                byte[] bytes = new byte[length];
                in.readBytes(bytes, 0, length);
                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                DataMsg dataMsg = (DataMsg) ois.readObject();
                log.debug("{}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);
                log.debug("{}", dataMsg);
                in.release();
                Message message = new MessageImpl();
                message.SetData(dataMsg.getData());
                message.SetDataLen(dataMsg.getDataLen());
                message.SetMsgId(dataMsg.getMsgId());
                return message;
            } catch (IOException | ClassNotFoundException e) {
//                throw new RuntimeException(e);
                log.info(e.getMessage());
            }
        }
        return null;
    }

    public static class DataMsg implements Serializable {
        private int sequenceId;
        private byte[] data;
        private int dataLen;

        private int msgId;

        public int getMsgId() {
            return msgId;
        }

        public void setMsgId(int msgId) {
            this.msgId = msgId;
        }

        public int getSequenceId() {
            return sequenceId;
        }

        public void setSequenceId(int sequenceId) {
            this.sequenceId = sequenceId;
        }

        public byte[] getData() {
            return data;
        }

        public void setData(byte[] data) {
            this.data = data;
        }

        public int getDataLen() {
            return dataLen;
        }

        public void setDataLen(int dataLen) {
            this.dataLen = dataLen;
        }
    }
}
